﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using System.Reflection;
using RawLevelFormat;

namespace theguineasyndrome
{
    abstract public class AppMode
    {
        public enum Mode
        {
            MENU,
            GAME,
            EDITOR
        };

        public static Mode mode;

        protected TheGuineaSyndromeGame game;

        protected GraphicsDevice graphicsDevice;
        protected SpriteBatch spriteBatch;
        protected ContentManager content;
        protected GameWindow window;

        protected Camera camera;
        protected Rectangle screenRectangle;
        protected Level level;

        protected KeyboardState currentKeyboardState;
        protected KeyboardState previousKeyboardState;

        protected MouseState currentMouseState;
        protected MouseState previousMouseState;

        protected GamePadState currentGamePadState;
        protected GamePadState previousGamePadState;

        protected GameTime currentTime;

        abstract public bool isFullScreen();

        public AppMode(TheGuineaSyndromeGame game, GraphicsDevice graphicsDevice, ContentManager content, GameWindow window)
        {
            this.game = game;
            this.graphicsDevice = graphicsDevice;
            this.content = content;
            this.window = window;
            this.screenRectangle = new Rectangle(0, 0, graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height);
        }

        public void setLevel(Level level)
        {
            this.level = level;

            camera = new Camera(new Vector2(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height), level);

            if (level.Right < camera.Width)
                level.Right = camera.Width;

            if (level.Bottom < camera.Height)
                level.Bottom = camera.Height;
        }

        public Level getLevel()
        {
            return level;
        }

        public virtual void Initialize()
        {
            currentKeyboardState = Keyboard.GetState();
            previousKeyboardState = currentKeyboardState;

            currentMouseState = Mouse.GetState();
            previousMouseState = currentMouseState;

            currentGamePadState = GamePad.GetState(PlayerIndex.One);
            previousGamePadState = currentGamePadState;

            currentTime = new GameTime();
        }

        public virtual void LoadContent()
        {
            spriteBatch = new SpriteBatch(graphicsDevice);
        }

        public virtual void UnloadContent()
        {

        }

        public virtual void Update(GameTime gameTime)
        {
            currentTime = gameTime;

            previousKeyboardState = currentKeyboardState;
            currentKeyboardState = Keyboard.GetState();

            previousMouseState = currentMouseState;
            currentMouseState = Mouse.GetState();

            previousGamePadState = currentGamePadState;
            currentGamePadState = GamePad.GetState(PlayerIndex.One);
        }

        public virtual void Draw(GameTime gameTime)
        {

        }

        public void refocus()
        {
            System.Windows.Forms.Form form = (System.Windows.Forms.Form)System.Windows.Forms.Form.FromHandle(this.window.Handle);
            form.Activate();
        }

        public virtual void notifyResize(Vector2 windowSize)
        {
            camera.setScreenSize(windowSize);

            if (level.Right < windowSize.X)
                level.Right = windowSize.X;

            if (level.Bottom < windowSize.Y)
                level.Bottom = windowSize.Y;

            screenRectangle.Width = (int)windowSize.X;
            screenRectangle.Height = (int)windowSize.Y;
        }

        public bool anyKeyPressed()
        {
            return currentKeyboardState.GetPressedKeys().Length > 0;
        }

        public bool isPressed(Keys key)
        {
            return currentKeyboardState.IsKeyDown(key);
        }

        public bool isJustPressed(Keys key)
        {
            return currentKeyboardState.IsKeyDown(key) && previousKeyboardState.IsKeyUp(key);
        }

        public bool isJustReleased(Keys key)
        {
            return currentKeyboardState.IsKeyUp(key) && previousKeyboardState.IsKeyDown(key);
        }

        public bool isPressed(string button)
        {
            Type type = typeof(MouseState);
            return (ButtonState)type.InvokeMember(button, BindingFlags.GetProperty, null, currentMouseState, null) == ButtonState.Pressed;
        }

        public bool isJustPressed(string button)
        {
            Type type = typeof(MouseState);
            return (ButtonState)type.InvokeMember(button, BindingFlags.GetProperty, null, currentMouseState, null) == ButtonState.Pressed
                && (ButtonState)type.InvokeMember(button, BindingFlags.GetProperty, null, previousMouseState, null) == ButtonState.Released;
        }

        public bool isJustReleased(string button)
        {
            Type type = typeof(MouseState);
            return (ButtonState)type.InvokeMember(button, BindingFlags.GetProperty, null, currentMouseState, null) == ButtonState.Released
                && (ButtonState)type.InvokeMember(button, BindingFlags.GetProperty, null, previousMouseState, null) == ButtonState.Pressed;
        }

        public Vector2 getPointer()
        {
            return new Vector2(currentMouseState.X, currentMouseState.Y);
        }

        public int getWheelDelta()
        {
            return currentMouseState.ScrollWheelValue - previousMouseState.ScrollWheelValue;
        }

        public Vector2 leftJoystick()
        {
            return currentGamePadState.ThumbSticks.Left;
        }

        public Vector2 rightJoystick()
        {
            return currentGamePadState.ThumbSticks.Right;
        }

        public bool isPressed(Buttons button)
        {
            return currentGamePadState.IsButtonDown(button);
        }

        public bool isJustPressed(Buttons button)
        {
            return currentGamePadState.IsButtonDown(button) && previousGamePadState.IsButtonUp(button);
        }

        public GameTime CurrentTime
        {
            get { return currentTime; }
        }

    }
}
